module Ministerio (Ministerio, agregarHotelM, secretariasM, registroM, nuevoM, cadenasDeHotelesM, cadenasAmarretasM, fusionAutorizadaM) where

import Tipos
import Reserva
import Habitacion
import Hotel

data Ministerio = REG Provincia Hotel Ministerio | MT [Provincia] deriving (Show)
-- (REG prov1 hot1 (REG prov1 hot2) (REG prov2 hot3 MT [prov1, prov2]) )

nuevoM :: [Provincia] -> Ministerio
nuevoM ps = MT ps

secretariasM :: Ministerio -> [Provincia]
secretariasM (MT ps) = ps
secretariasM (REG _ _ m) = secretariasM m

registroM :: Ministerio -> Provincia -> [Hotel]
registroM (MT p) = []
registroM (REG prov ht m) p = if (prov == p) then ht:(registroM m p) else (registroM m p)

cadenasDeHotelesM :: Ministerio -> [[Hotel]]
cadenasDeHotelesM m = cadenasDeHotelesAux (m listaCadenas h)

agregarHotelM :: Ministerio -> Hotel -> Provincia -> Ministerio
agregarHotelM m h p = REG p h m 

cadenasAmarretasM :: Ministerio -> [Cadena]
cadenasAmarretasM m = cadenasQueEstanEnMenosProvincias m

fusionAutorizadaM :: Ministerio -> Cadena -> Cadena -> Ministerio
fusionAutorizadaM m c1 c2 = fusionar (cadenasDeHotelesM m) c1 c2 (MT (secretariasM m))


----------------
-- Auxiliares --
----------------

-- cadenasDeHotelesM --
cadenasDeHotelesAux :: Ministerio -> [Cadena] -> [[Hotel]]
cadenasDeHotelesAux m [] = []
cadenasDeHotelesAux m (c:cs) = hotelesDeCadena(m c):cadenasDeHotelesAux(m cs) 

listaCadenas :: Ministerio -> [Cadena]
listaCadenas h = sacarRepetidos(listaCadenasAux(h))

listaCadenasAux :: Ministerio -> [Cadena]
listaCadenasAux (MT [Provincia]) = []
listaCadenasAux (REG _ h m) = h:listaCadenasAux(m)

hotelesDeCadena:: Ministerio -> Cadena -> [Hotel]
hotelesDeCadena MT [Provincia] c = []
hotelesDeCadena (REG p h m) c
                   |cadena(h) == c = h:hotelesDeCadena(m c)
                   |otherwise = hotelesDeCadena(m c)

-- cadenasAmarretasM --

cadenasQueEstanEnMenosProvincias :: Ministerio -> [Cadena]
cadenasQueEstanEnMenosProvincias m = dameCadenasConPresencia (todasLasCadenas m) (cantMinima (todasLasCadenas m) m) m

todasLasCadenas :: Ministerio -> [Cadena]
todasLasCadenas m = aplanarCadenas (cadenasDeHotelesM m)

aplanarCadenas :: [[Hotel]] -> [Cadena]
aplanarCadenas (hs:[]) = cadenaH (hs !! 0)
aplanarCadenas (hs:hss) = (cadenaH (hs !! 0)) : (aplanarCadenas hss)

dameCadenasConPresencia :: [Cadena] -> Int -> Ministerio -> [Cadena]
dameCadenasConPresencia c:[] n = if (presencia c m) == n then [c] else []
dameCadenasConPresencia c:cs n = if (presencia c m) == n then [c] ++ (dameCadenasConPresencia cs) else dameCadenasConPresencia cs

cantMinima :: [Cadena] -> Ministerio -> Int
cantMinima (c:[]) m = presencia c m
cantMinima (c:cs) m = if (presencia c m) < (cantMinima cs m) then presencia c m else cantMinima cs m 

presencia :: Cadena -> Ministerio -> Int
presencia c m = enCuantasProvinciasEsta c m (secretariasM m)

enCuantasProvinciasEsta :: Cadena -> Ministerio -> [Provincia] -> Int
enCuantasProvinciasEsta c m (p:[]) = if (estaCadena c (registroM m p)) then 1 else 0
enCuantasProvinciasEsta c m (p:ps) = (if (estaCadena c (registroM m p)) then 1 else 0) + (enCuantasProvinciasEsta c m ps)

estaCadena :: Cadena -> [Hotel] -> Bool
estaCadena c (h:[]) = (cadenaH h) == c
estaCadena c (h:hs) = (cadenaH h) == c || (estaCadena hs)

-- fusionAutorizadaM --

fusionar :: [[Hotel]] -> Cadena -> Cadena -> Ministerio -> Ministerio
fusionar ((h:[]):[]) c1 c2 m = 
            if (cadenaH h) == c1 
            then REG (provinciaDeHotel h m) (nuevoH (nombreH h) c2 (habitacionesH h) (tarifasXDiaH h) (precioAccesorioH h)) m
            else REG (provinciaDeHotel h m) (nuevoH (nombreH h) (cadenaH h) (habitacionesH h) (tarifasXDiaH h) (precioAccesorioH h)) m

fusionar ((h:hs):[]) c1 c2 m = 
            if (cadenaH h) == c1 
            then REG (provinciaDeHotel h m) (nuevoH (nombreH h) c2 (habitacionesH h) (tarifasXDiaH h) (precioAccesorioH h)) (fusionar hs c1 c2 m)
            else REG (provinciaDeHotel h m) (nuevoH (nombreH h) (cadenaH h) (habitacionesH h) (tarifasXDiaH h) (precioAccesorioH h)) (fusionar hs c1 c2 m)

fusionar (h:(hs:hss)) c1 c2 m = 
            if (cadenaH h) == c1 
            then REG (provinciaDeHotel h m) (nuevoH (nombreH h) c2 (habitacionesH h) (tarifasXDiaH h) (precioAccesorioH h)) (fusionar (hs:hss) c1 c2 m)
            else REG (provinciaDeHotel h m) (nuevoH (nombreH h) (cadenaH h) (habitacionesH h) (tarifasXDiaH h) (precioAccesorioH h)) 
(fusionar (hs:hss) c1 c2 m)

provinciaDeHotel :: Hotel -> Ministerio -> Provincia
provinciaDeHotel h m = buscarEnProvincias h (secretariasM h)

buscarEnProvincias :: Hotel -> [Provincia] -> Provincia
buscarEnProvincias h (p:[]) = p
buscarEnProvincias h (p:ps) = if elem h (registroM m p) then p else buscarEnProvincias h ps

